﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

#pragma once
#include "GmepBaseInteraction.h"
#include "IArc3d.h"
#include "Vector3d.h"
#include "ILine3d.h"
#include "IGmepConstDefinition.h"
#include "IMepCurve.h"
#include "IMepSystemType.h"
#include "IConnector.h"
#include "IMepDevice.h"
#include "ElementId.h"
#include "IMepFitting.h"
#include "UniIdentity.h"
#include "IMepInstance.h"

#include "IUiView.h"
#include "IAnnotationText.h"
#include "GmepBuiltInParameterStaticVauleListItems.h"
#include "IParameterValueStorage.h"
#include "QMap"
#include "QString"
#include "GnufAnnouncement.h"
#include "IGmepCategoryInfo.h"
#include "IGraphicsPicture.h"
#include "IDuct.h"
#include "SearchNode.h"
#include "IPickFilter.h"
#include "IGraphicsNode.h"

#define GMEP_FAMILY_FILE_EXT      L".gac"

namespace gmep
{
    class ISystemTypeData;
    class IProjectSettingSystemType;
    class IProjectSettingSystemMaterialSerie;
    enum class GmepProjectSettingTableId;
    class IProjectSettingMEPMaterialSerie;
    class IGmepDataset;
    struct Gmep2DFamilyInfo;
    class IMepSystem;
    class IMepProvisionOpeningNew;
}

namespace gcmp
{
    class CommandParameters;
    class ISnap;
    class IParameterValueStorage;
}

class ItemData;
class QWidget;

namespace gmep
{
    // 直线、圆弧按个数布置参数
    struct MepDeviceGroup
    {
        gcmp::Vector3d PrjectPt = gcmp::Vector3d::Zero;
        std::vector<gmep::IMepDevice*> listMepDevices = {};

        //管道左侧设备ID
        std::vector<gcmp::ElementId> leftDeviceIdByPipe = {};
        //管道右侧设备ID
        std::vector<gcmp::ElementId> rightDeviceIdByPipe = {};

        gcmp::ElementId currentId = gcmp::ElementId::InvalidID;
        MepDeviceGroup()
        {
        }
    };
    //////////封装创建组合阀件公用函数begin  add by yangpan////////////////////////////////////////////////////////////////
    struct ValvesInfo
    {
        std::wstring strValvesName = L"";         // 名称
        std::wstring strValvesType = L"";         // 阀件类型名称（PipeValve,PipeAccessory）
        std::wstring strValvesFamily = L"";       // 族文件名
        std::wstring strValvesImage = L"";        // 三维图片
        std::wstring strValvesImage2D = L"";      // 二维图片

        std::wstring strFamily2DPlane = L"";
        std::wstring strFamily2DRightLeftElevation = L"";
        std::wstring strFamily2DFrontBackElevation = L"";
        std::wstring strFamily2DElectric;

        bool bIsCombin = false;                     // 是否能组成组合阀
        QMap<QString, QString> map = {};
        Int64 familyIdInCloud = 0;  //DB3中的Id
        int iVersion = 0;           //DB3中的Version
    };
    // 组合阀件信息
    struct ComposeValvesInfo
    {
        std::wstring id;          // 组合阀Id
        std::wstring name;          // 组合阀名称
        std::vector<ValvesInfo> arrValvesInfo;      // 组合阀包含的阀件
        double dValvesDist;                         // 阀件净距
        QMap<QString, QString> map;

        ComposeValvesInfo()
        {
            id = L"";
            name = L"";
            arrValvesInfo.clear();
            dValvesDist = 0.0;
            map.clear();
        }
    };
    //////////////////////////////////////////////////////////////////////////
    class GMEP_BASE_INTERACTION_EXPORT GjwPlaceInstanceInfo
    {
        CANNOT_COPY_OR_ASSIGN(GjwPlaceInstanceInfo);
    public:
        static GjwPlaceInstanceInfo& Get();
        GjwPlaceInstanceInfo() {}
        std::map<std::wstring, OwnerPtr<gcmp::IParameterValueStorage>> m_mapInstanceProperty;
    };

    class GMEP_BASE_INTERACTION_EXPORT BaseInteractionUtils
    {
    public:
        BaseInteractionUtils();
        ~BaseInteractionUtils();

        static gcmp::IUiDocument* GetCurrentUIDoc();
        //机电专业分类
        static bool GetMEPDisciplineId(gcmp::IDocument * pDoc, const gmep::IMepElement* pMepCurve, gmep::MEPDisciplineId& mepDisciplineId);
        static bool GetMEPDisciplineId(gcmp::IDocument* pDoc, gmep::MEPSystemClassification mepClass, gmep::MEPDisciplineId& mepDisciplineId);

        // 检查给排水 暖通 电气的系统类型， 若没有 跳出项目未配置的提示并导航至项目配置对话框
        static bool CheckMepDisciplineIdSystemTypes(gcmp::IDocument* pDoc, gmep::GmepProjectSettingTableId table);

        // 跳出项目未配置的提示并导航至项目配置对话框
        static void ShowMessageToOpenProjectSettingDialog(const std::wstring& strWarningText);

        static const gmep::MEPSystemClassification GetMepSystemClass(gcmp::IDocument * pDoc, const gmep::IMepElement* pMepElement);

        static const std::wstring GetMepElementSystemName(gcmp::IDocument * pDoc, gmep::IMepElement * pMepCurve);
        static const std::wstring GetMepElementSystemName(gcmp::IDocument * pDoc, const gcmp::IElement* pMepCurve);

        static std::wstring GetMepInstanceTypeSystemName(gmep::IMepInstance* pMepInstance);
        static std::wstring GetMepInstanceTypeSystemName(const gmep::IMepInstance* pMepInstance);


        /*static const gmep::MEPSystemClassification GetConnSystemClass(const gcmp::IDocument * pDoc, const gmep::IConnector * pMepCurve);
        static const gmep::MEPSystemClassification GetConnSystemClass(gcmp::IDocument * pDoc, gmep::IConnector * pMepCurve);*/
        static const gmep::IMepSystemType* GetConnSystemType(const gcmp::IDocument * pDoc, gmep::IConnector * conn);
        static const gmep::IMepSystemType* GetConnSystemType(const gcmp::IDocument * pDoc, const gmep::IConnector * conn);
        static const std::wstring GetConnSystemName(const gcmp::IDocument * pDoc, gmep::IConnector * conn);
        static const std::wstring GetConnSystemTypeName(const gcmp::IDocument * pDoc, gmep::IConnector * conn);
        static const std::wstring GetConnSystemTypeName(const gcmp::IDocument * pDoc, const gmep::IConnector * conn);


        //获得管道直接连接的设备管件
        static std::vector<const gmep::IMepInstance*> GetMepCurveConnectedMepInstance(gcmp::IDocument* pdoc, const gmep::IMepCurve* pMepCurve);

        static gcmp::ElementId GetLinkedInstanceTypeId(gcmp::IDocument * pMainDoc, gcmp::IDocument * pLinkDoc,
            const gcmp::ElementId instanceTypeId, const gcmp::UniIdentity categoryUid,
            std::map<gcmp::UniIdentity, gcmp::ParameterStorageType> mapParams);
        static bool SetLinkedInstanceTypeParameter(gcmp::IDocument * pMainDocument, gcmp::IDocument * pLinkedDocument, gcmp::IInstanceType * pCasingRetInstanceType, gcmp::ElementId mainInstanceTypeId, const std::map<gcmp::UniIdentity, gcmp::ParameterStorageType> &mapParams);

        static bool SetLinkedInstanceTypeAllParameter(gcmp::IDocument * pLinkedDocument
            , gcmp::IInstanceType * pLinkInstanceType, gcmp::ElementId mainInstanceTypeId
            , const std::map<gcmp::UniIdentity, gcmp::OwnerPtr<gcmp::IParameterValueStorage>> &mapParams);
        static bool isMepDevice(gmep::IMepElement* pMepCurve);
        static bool isOwnMepDevice(const gcmp::IDocument * pDoc, gmep::IConnector * conn);

        static gcmp::ElementId GetPipeTypeIds(gcmp::IDocument* pDoc);

        // 获取Element的类别
        static bool GetElementCategory(const gcmp::IDocument* pDoc, const gcmp::ElementId& id, gcmp::UniIdentity& uid);
        static bool GetElementCategory(const gcmp::IElement* pElement, gcmp::UniIdentity& uid);
        // 获取MepInstance名称
        static bool GetMepInstanceTypeName(const gmep::IMepInstance* pMepInstance, std::wstring& strName);
        // 获取MepInstance族名称
        static bool GetMepInstanceFamilyName(const gmep::IMepInstance* pMepInstance, std::wstring& strName);


        //按照到基准线的距离排序，根据连接点的投影
        static std::vector<gmep::IMepDevice*> GetOrderedMepDevices(std::vector<gmep::IMepDevice*> IMepDevices, gcmp::ILine3d* baseLine);

        static bool IsExistProjectPoint(std::vector<MepDeviceGroup> mepDeviceGroupInfo, gcmp::Vector3d projectPt, int& indexOfDeviceInGroup, double tolerance = 3);

        static bool IsDeviceInSameHeight(std::vector<gmep::IMepDevice*> IMepDevices);

        static gmep::IConnector* GetConnectorFWByConstConnector(const gcmp::IDocument * pDoc, const gmep::IConnector* pConnector);

        //对设备进行排序，返回的是投影点是一组的将认为是一个MepDeviceGroup, 这些MepDeviceGroup之间按照一个方向进行排序，将沈忱沈工写的代码移植到这里,  modify by wzj 2020-07-10
        //添加默认容差，默认为3；
        static std::vector<MepDeviceGroup> GroupMepDevices(std::vector< gmep::IMepDevice*> sprinkles, gmep::IMepCurve* pipe, bool isConsiderZ, double tolerance = 3, bool rectHvacNeedProject = true);

        //对设备进行排序，返回的是投影点是一组的将认为是一个MepDeviceGroup, 这些MepDeviceGroup之间按照一个方向进行排序，将沈忱沈工写的代码移植到这里,  modify by wzj 2020-07-10
        static std::vector<MepDeviceGroup> GroupMepDevices(const gcmp::IDocument * pDoc, std::vector<gmep::IMepDevice*> sprinkles, std::vector<gcmp::ElementId> pipes, bool isConsiderZ, double tolerance = 3);

        static gmep::IMepCurve* GetMinDistanceDuct(const gcmp::IDocument * pDoc, gmep::IMepDevice * air, std::vector<gcmp::ElementId> pipes);

        /// \brief 判断机电设备上是否有电气连接点
        static bool IsContainElectricalConnector(const gcmp::IElement* pElement);

        // 创建组合阀件(跨管道)
       // \param[in] pos 创建位置
       // \param[in] strComposeValvesName 阀组Id
       // \param[in] pRefMepCurve 放置的管道
       // \param[in] dInletDiameter 管径
       // \param[in] layValvesDir 排列方向
       // \param[out] arrValvesIds 阀件Ids
       // \param[out] arrMepCurveIds 打断新生成的管道Ids
       // \param[in] mepCurveFilterIds 过滤附加的管道Ids
        static bool CreateComposeValvesFamily(gcmp::IDocument * pDoc, const std::wstring & strComposeValvesId, gmep::IMepCurve * pRefMepCurve,
            const gcmp::Vector3d & pos, gcmp::Vector3d layValvesDir,
            gcmp::ElementIdArray & arrValvesIds, gcmp::ElementIdArray & arrMepCurveIds, gcmp::ElementIdArray mepCurveFilterIds = gcmp::ElementIdArray());

        // 创建组合阀件(跨管道)
        // \param[in] pos 创建位置
        // \param[in] composeValvesInfo 阀组Info
        // \param[in] pRefMepCurve 放置的管道
        // \param[in] dInletDiameter 管径
        // \param[in] layValvesDir 排列方向
        // \param[out] arrValvesIds 阀件Ids
        // \param[out] arrMepCurveIds 打断新生成的管道Ids
        // \param[in] mepCurveFilterIds 过滤附加的管道Ids
        static bool CreateComposeValvesFamily(gcmp::IDocument* pDoc, const ComposeValvesInfo& composeValvesInfo, gmep::IMepCurve* pRefMepCurve,
            const gcmp::Vector3d& pos, gcmp::Vector3d layValvesDir, double dOffset, gcmp::ElementIdArray& arrValvesIds, gcmp::ElementIdArray& arrMepCurveIds, gcmp::ElementIdArray mepCurveFilterIds = gcmp::ElementIdArray());

        // 创建组合阀件(跨管道)
        // \param[in] arrInstanceTypeIds 阀组Id
        // \param[in] pRefMepCurve 放置的管道
        // \param[in] pos 创建位置
        // \param[in] dValvesDist 阀组间距
        // \param[in] layValvesDir 排列方向
        // \param[out] arrValvesIds 阀件Ids
        // \param[in] mepCurveFilterIds 过滤附加的管道Ids
        static bool CreateComposeValvesFamily(gcmp::IDocument * pDoc, gcmp::ElementIdArray arrInstanceTypeIds, gmep::IMepCurve * pRefMepCurve,
            const gcmp::Vector3d & pos, double dOffset, double dValvesDist, gcmp::Vector3d layValvesDir,
            gcmp::ElementIdArray & arrValvesIds, gcmp::ElementIdArray & arrMepCurveIds, gcmp::ElementIdArray mepCurveFilterIds = gcmp::ElementIdArray());

        // 创建组合阀件(不跨管道)
        // \param[in] pValves 阀门Ids
        // \param[in] pRefMepCurve 放置的管道
        // \param[in] pos 创建位置
        // \param[in] dValvesDist 阀组间距
        // \param[in] layValvesDir 排列方向
        static bool CreateComposeValvesFamily(gcmp::IDocument* pDoc, std::vector<gmep::IMepDevice*> pValves, gmep::IMepCurve* pRefMepCurve, const gcmp::Vector3d& pos,
            double dValvesDist, gcmp::Vector3d layValvesDir);

        // 创建阀件
        // \param[in] instanceTypeId 阀件Id
        // \param[in] levelId 标高Id
        // \param[in] pos 布置位置
        // \param[in] layDir 布置方向
        // \param[in] dInletDiameter 内径
        static gmep::IMepDevice * CreateValveFamily(gcmp::IDocument * pDoc, const gcmp::ElementId & instanceTypeId, const gcmp::ElementId & levelId,
            const gcmp::Vector3d & pos, gcmp::ElementCreationOptions eco = gcmp::ElementCreationOptions::Normal);

        // 创建孔洞套管
        // \param[in] instanceTypeId 阀件Id
        // \param[in] levelId 标高Id
        // \param[in] pos 布置位置
        // \param[in] layDir 布置方向
        // \param[in] dInletDiameter 内径
        static gmep::IMepProvisionOpeningNew * CreateProvisionOpeningFamily(gcmp::IDocument * pDoc, const gcmp::ElementId & instanceTypeId, const gcmp::ElementId & levelId,
            const gcmp::Vector3d & pos, gcmp::ElementCreationOptions eco = gcmp::ElementCreationOptions::Normal);

        //组合阀门同时设置实例参数
        // \param[in] arrMepCurveIds 标高 族实例的id的数组
        // \param[in] InstancePropertyLists 族类型参数的list （两个需一一匹配）
        static void SetPropertyValueList(gcmp::IDocument * pDoc, const gcmp::ElementIdArray arrValvesIds, std::vector<std::map<std::wstring, gcmp::OwnerPtr<gcmp::IParameterValueStorage >>> InstancePropertyLists);

        // 得到所有组合阀
        static bool GetAllComposeValves(bool isHVAC, std::vector<ComposeValvesInfo>& arrComposeValvesInfo);

        // 得到阀件的满足组合阀条件的连接点数组
        static bool GetConnectorsOfValves(const gmep::IMepDevice* pValve, std::vector<const gmep::IConnector*>& arrConnectors, bool bIsOnRiserPipe = false);

        // 得到阀件的满足组合阀条件的连接点数组
        static bool GetConnectorsOfValvesFW(gmep::IMepDevice* pValve, std::vector<gmep::IConnector*>& arrConnectors, bool bIsOnRiserPipe = false);
        static bool GetConnectorsOfDuctValves(const gmep::IMepDevice * pValve, std::vector<const gmep::IConnector*>& arrConnectors, bool bIsOnRiserPipe = false);

        static int GetValvesType(const gmep::IMepDevice * pValve);

        static gcmp::IInstanceType* GetIMepDevicesType(gmep::IMepDevice * pMepDevice);

        static const gcmp::IInstanceType* GetIMepDevicesType(const gmep::IMepDevice * pMepDevice);

        static bool IsValveRiser(gmep::IMepDevice * pValve);
        static bool IsValveRiser(const  gmep::IMepDevice * pValve);

        static bool IsValveRiser(gmep::IMepDevice * pValve, gmep::IConnector*& mainConn);

        // 得到距离指定点最近的连接点
        static gmep::IConnector* GetNearestConnector(const std::vector<gmep::IConnector*>& arrConnectors, const gcmp::Vector3d& refPoint);

        //////////封装创建组合阀件公用函数end    add by yangpan////////////////////////////////////////////////////////////////

        // 根据ConnectorId获取设备的连接点位置 
        static bool GetConnectPosition(const gmep::IMepDevice *pMepDevice, gcmp::Vector3d &connectPosition, int nConnectId = 0);
        static bool GetDeviceConnectorPosAndDir(const gmep::IMepDevice *pMepDevice, gcmp::Vector3d &connectorPosition, gcmp::Vector3d &connectorDirection, int nConnectId = 0);
        //得到元素的位置
        static bool GetMepDevicePos(const gcmp::IElement* pElement, gcmp::Vector3d& pntMepDevice);
        static bool GetMepDevicePos(const gcmp::IDocument* pDoc, const gcmp::ElementId& elementId, gcmp::Vector3d& pntMepDevice);
        static bool GetMepDeviceFirstConnectorDiameter(const gmep::IMepDevice* pMepDevice, double& dDiameter);
        // 字符串大小写转换
        static std::wstring ToUpper(const std::wstring& strSource);
        static std::wstring ToLower(const std::wstring& strSource);

        // 创建二维线
        static gcmp::ElementId DrawDetailLine(gcmp::IModelView* pModelView, const gcmp::Vector3d& startPt,
            const gcmp::Vector3d& endPt, const gcmp::ElementId& lineStyleId = gcmp::ElementId::InvalidID);

        static gcmp::ElementId DrawDetailLine(gcmp::IModelView* pModelView, gcmp::OwnerPtr<gcmp::ICurve2d> opCurve3d, const std::wstring & styleName);

        //创建文字
        static gcmp::IAnnotationText* DrawAnnotationText(gcmp::IUiView* pUiView, std::wstring textContent, gcmp::Vector3d location, gcmp::Vector3d textDirection);

        //刷新文档
        static bool RegenerateDocument(gcmp::IDocument* pdoc);
        //获取安装方式
        static gmep::InstallationType GetInstallationType(std::map<std::wstring, const gcmp::IParameterValueStorage *> proPertyList);

        //获取卫浴设备安装方式
        static gmep::InstallationType GetBathRoomInstallType(const gcmp::IElement* pTypeElement);
        static gmep::InstallationType GetBathRoomInstallType(const std::wstring wsBathRoomInstallType);

        static std::wstring GetBathRoomApplianceTypeName(const gmep::BathRoomApplianceType &bathRoomApplianceType);

        static int DrawSelectConnector(gcmp::IUiView* pCurrentView, const gmep::IConnector* con, const gmep::IConnectorManager* imanage, gmep::MEPSystemClassification connClassification, const gmep::IConnector*& res);

        static QString getConnectInfoValue(const gmep::IConnector* con);

        static const gmep::IMepInstance* GetPickedMepInstanceAndPickElementId(gcmp::IUiView* pCurrentView, gcmp::IDocument* pDoc, const gcmp::Vector3d & curPoint, double dPickTolerance, gcmp::ElementId& pickedElementId);

        static const gmep::IMepInstance* GetPickedMepInstance(gcmp::IUiView* pCurrentView, gcmp::IDocument* pDoc, const gcmp::Vector3d & curPoint, double dPickTolerance);

        static const gmep::IMepInstance* GetPickedMepInstanceByHighlight(gcmp::IUiView* pCurrentView, gcmp::IDocument* pDoc);

        static const gmep::IMepDevice* GetPickedMepDevice(gcmp::IUiView* pCurrentView, gcmp::IDocument* pDoc, const gcmp::Vector3d & curPoint, double dPickTolerance);
        /// \brief 通过当前点来获得与其相交的管线Id；
        static  gcmp::ElementId GetPickedMepCurveId(gcmp::IUiView* pCurrentView, const gcmp::IDocument* pDoc, const gcmp::Vector3d & mousePoint,
            double dPickTolerance, gcmp::IPickFilter* pPickFilter, const std::vector<gcmp::ElementId>& arrFilterMepCurveIds);

        // 根据鼠标点获取容差范围内的所有实体
        static bool GetPickedAllGraphicsNode(gcmp::IUiView* pCurrentView, const gcmp::Vector3d& pos, double dPickTolerance, std::vector<gcmp::OwnerPtr<gcmp::IGraphicsNodeReference>>& arrGNodeReference);

        static const gmep::IConnector* GetMepDeviceNearestPoint(gcmp::IModelView* pmodelView, bool m_isElevationView, const gcmp::Vector3d& mousePt,
            const gmep::IMepInstance* pMepInstance, const gmep::IConnectorManager*& cManager, gmep::ConnectorDomain domain, double LimitDistance, std::vector<const gmep::IConnector*>& customSnapConnectors);

        /// \brief 获取管道距指定点最近的连接点
        static const gmep::IConnector* GetMepCurveNearestPoint(gcmp::IModelView* pmodelView, bool m_isElevationView, const gcmp::Vector3d& mousePt,
            const gmep::IMepCurve* pMepInstance, const gmep::IConnectorManager*& cManager, gmep::ConnectorDomain domain, double LimitDistance,
            std::vector<const gmep::IConnector*>& customSnapConnectors);

        /// \brief 根据连接点管理器获取距指定点最近的连接点
        static const gmep::IConnector* GetNearestPointByConnectorManager(gcmp::IModelView* pmodelView, bool m_isElevationView, const gcmp::Vector3d& mousePt,
            const gmep::IConnectorManager* pConnectorManager, gmep::ConnectorDomain domain, double LimitDistance, std::vector<const gmep::IConnector*>& customSnapConnectors);

        //获取属性的类别
        static gcmp::OwnerPtr<gmep::IGmepCategoryInfo> GetCategoryInfo(gcmp::UniIdentity categoryGuid);

        static gcmp::OwnerPtr<gcmp::IGraphicsPicture> DrawTempConnPreviewGraphicsShape(const gmep::IConnector* pSnapConnector);

        static bool IsSubWaterForbiddenConn(const gmep::IConnector* pConnector);

        //******************视图可见性*********************
        // pElement在当前视图是否可见
        static bool IsElementVisible(const gcmp::IElement* pElement, std::wstring* pInvisibleReason = nullptr);
        // pElement在pUiView当前视图是否可见
        static bool IsElementVisible(const gcmp::IUiView* pUiView, const gcmp::IElement* pElement, std::wstring* pInvisibleReason = nullptr);

        //元素在当前视图是否可见
        static void CheckElementVisible(const IElement* pElement);
        static void CheckElementVisible(const std::vector<gcmp::IElement*> pElements);
        static void CheckElementVisible(const std::vector<gmep::IMepDevice*> pMepDevices);
        static void CheckElementVisible(gcmp::IDocument* pDoc, const std::vector<gcmp::ElementId> elementIds);

        //系统类型在当前视图是否可见
        static bool GetElementsVisibilityByMepSystemType(const gmep::IMepSystemType* pMepSystemType);
        //高度是否在视图范围内
        static bool IsInModelViewRange(double z);
        //高度是否高出视图范围
        static bool IsTopThanModelViewRange(double z);
        //高度是否低于视图范围
        static bool IsLowerThanModelViewRange(double z);

        //高度是否高出或等于视图范围
        static bool IsTopThanOrEqualModelViewRange(double z);
        //高度是否低于或等于视图范围
        static bool IsLowerThanOrEqualModelViewRange(double z);

        // 移动阀件
        static bool MoveValves(gmep::IMepDevice* pValves, gcmp::Vector3d moveVec);

        //右键创建实例公共方法 yucx add 2021-01-27
        static bool GetSimilarActionDrawGmepInstance(gcmp::IDocument* pDoc, const gcmp::CommandParameters cmdParams, std::map<std::wstring, gcmp::OwnerPtr<gcmp::IParameterValueStorage >> &InstanceList, gcmp::IElementParameters* &pInstanceParameters);
        // 孔洞套管基础的创建类似实例
        static bool GetSimilarInstanceActionDrawGmepInstance(gcmp::IDocument* pDoc, const gcmp::CommandParameters cmdParams, std::map<std::wstring, gcmp::OwnerPtr<gcmp::IParameterValueStorage >> &InstanceList, gcmp::IElementParameters* &pInstanceParameters);
        static std::wstring ParseCmdParamsForCategoryUID(const gcmp::CommandParameters cmdParams);
        static gcmp::ElementId ParseCmdParamsForFamilyId(const gcmp::CommandParameters cmdParams);
        static gcmp::ElementId ParseCmdParamsForInstanceTypeId(const gcmp::CommandParameters cmdParams);
        static gcmp::ElementId ParseCmdParamsForElementId(const gcmp::CommandParameters cmdParams);

        static void UpdateInstanceParameterByGjw(std::map<std::wstring, OwnerPtr<gcmp::IParameterValueStorage>>& mapInstanceProperty);

         //由IElementParameters取得参数列表 yucx add 2021-02-02
        static const bool GetItemDataByCategory(const gcmp::UniIdentity &categoryId, gcmp::IElementParameters* pParas, std::vector<ItemData>& lstProductParm);
        static std::map<std::wstring, const gcmp::IParameterValueStorage *> GetAllProductParmListByCategory(gcmp::IElementParameters* pParas);

        //创建纵向管道以及与设备的连接associatedPlaneId为管道所在平台Id
        static gmep::IMepCurve* CreateVerMepCurveAndConnectionToDevice(gcmp::IDocument* pDoc, gmep::IMepDevice* pDevice, gmep::IMepCurve* pBranchMepCurve, gcmp::ElementId associatedPlaneId);
        //创建风管
        static gmep::IDuct* CreateDuct(gcmp::IDocument* pDoc, std::vector<gcmp::Vector3d>vecDuctEndPoints, std::vector<double>vecDuctSpecification, bool isRoundDuct, gcmp::Vector3d curveHeighNormal, gcmp::ElementId associatedPlaneId, const gcmp::ElementId& systemId);

        //提取所有连接的管道
        static void GetAllLinkedMepCurves(gcmp::IDocument* pDocument, gmep::IMepCurve* pickedElement, std::vector<gmep::IMepCurve*>& vecAllLinkedMepCurves);
        //提取所有连接的管道
        static void GetAllLinkedMepCurves(gcmp::IDocument* pDocument, gmep::IMepCurve* pickedElement, gcmp::Vector3d directionPosition, std::vector<gmep::IMepCurve*>& vecAllLinkedMepCurves);
        static void  GetAllLinkedMepCurves(gcmp::IDocument* pDocument, AlgorithmMep::SearchNode * pSearchNode, std::vector<gmep::IMepCurve*>& vecAllLinkedMepCurves);

        //找到与提供管道相连的所有管道
        static std::vector<gmep::IMepCurve*>GetAllLinkedMepCurvesOfMepCurve(gcmp::IDocument* pDocument, gmep::IMepCurve* pMepCurve);

        //按照设备到管道的最小距离进行分组
        static void GroupDevicesByDistanceToMepCurve(std::map<gcmp::ElementId, std::vector<gcmp::ElementId>>& mepCurveMapDevices, std::vector<gmep::IMepCurve*>vecMepCurves, std::vector<gmep::IMepDevice*>vecDevices
            , gmep::ConnectorDomain connectDomain = gmep::ConnectorDomain::DomainUndefined, double offsetLength = 0);

        //按照设备到管道系统的最小距离进行分组
        static void GroupDevicesByDistanceToMepCurveSystem(std::map<gcmp::ElementId, std::vector<gcmp::ElementId>>& mepCurveMapDevices, gmep::IMepCurve* pFirstMepCurve, std::vector<gmep::IMepDevice*>vecDevices, gcmp::IDocument* pDocument
            , gmep::ConnectorDomain connectDomain = gmep::ConnectorDomain::DomainUndefined, double offsetLength = 0, bool isSearchConnectMepCurve = true);

        //提取设备的所有坐标系
        static std::vector<gcmp::Coordinate3d>GetCoordinateOfDevice(const gmep::IMepDevice* pDevice);
        //提取设备连结点的坐标系
        static gcmp::Coordinate3d GetCoordinateOfDeviceConnector(const gmep::IMepDevice* pDevice);

        //判断设备是否可以连接到管道，判断标准为：判断投影点是否在管道上，如果在则可以；如果不在管道上，查找最近连接点，并判断连接点是否可以移动
        static bool IsDeviceCanConnectToMepCurve(const gmep::IMepDevice* pDevice, gmep::IMepCurve* pMepCurve);
        static bool IsDeviceCanConnectToMepCurve(gcmp::Vector3d devicePoint, gmep::IMepCurve* pMepCurve);

        //提取设备在一个方向上的长度,directionOfLength,设备方向
        static double GetLengthOfDeviceByDirection(const gmep::IMepDevice* pDevice, gcmp::Vector3d directionOfLength);

        //通过阀件获得映射表CombinationPipeValveList对应的id yucx add 2021-02-03
        static QString GetCombinationValveListId(bool isHVAC, bool isValve, QString familyId);

        //通过字符串获取迭代器，不区分大小写字符串
        static std::map<std::wstring, gcmp::OwnerPtr<gcmp::IParameterValueStorage>>::iterator FindParameterIter(std::map<std::wstring, gcmp::OwnerPtr<gcmp::IParameterValueStorage>>& mapCmdParams, const std::wstring& strMatch);
        //亮显
        static void SetHighLightElements(IDocument*pDocument, const std::vector<gcmp::ElementId>& ids);

        static void SetHighLightElement(IDocument* pDocument, const gcmp::ElementId& id);

        static void SetSelectedAndHighLightElements(IDocument* pdoc, std::vector<gcmp::ElementId> ids);

        static bool GetConnValveClassification(gcmp::IDocument* pDoc, const gmep::IConnector* connector, gmep::MEPSystemClassification& systemClassification, const gmep::IMepSystemType*& systemType);

        static std::wstring Get2DSymbolPath(const std::wstring& databaseName, const std::wstring& s2DSymbolId);
        static void Get2DSymbolPath(const std::wstring& databaseName, std::map<std::wstring, std::wstring>& mapSymbolIdName);

        // 设置当前Action光标类型
        static void SwitchActionCursorType(gcmp::CursorType cursorType);

        //通过 子category 获取父 cateGory
        /// \brief 根据传入的guid获取父节点的guid
        /// \param pDoc 文档
        /// \param strGuid guid字符串，注意不带大括号的字符串
        /// \param parentUid 父节点的guid
        /// \return 成功或失败
        static bool GetParentUidByUid(gcmp::IDocument* pDoc, const std::wstring& strGuid, gcmp::UniIdentity& parentUid);
        static bool GetParentUidByUid(gcmp::IDocument* pDoc, const gcmp::UniIdentity& guid, gcmp::UniIdentity& parentUid);

        /// \brief 根据传入的guid获取子节点的guid
        /// \param pDoc 文档
        /// \param strGuid guid字符串，注意不带大括号的字符串
        /// \param arrChildrenUid 子节点的guid
        /// \return 成功或失败
        static bool GetChildrenUidByUid(gcmp::IDocument* pDoc, const std::wstring& strGuid, std::vector<gcmp::UniIdentity>& arrChildrenUid);
        static bool GetChildrenUidByUid(gcmp::IDocument* pDoc, const gcmp::UniIdentity& guid, std::vector<gcmp::UniIdentity>& arrChildrenUid);

        //设置视图捕捉平面
		static void SetSnapPlaneForView(gcmp::IModelView* pModelView, const gcmp::Vector3d& endPoint,
			double levelElevation, double offset, const gmep::IMepCurve* pMepCurve = nullptr);
        //设置工作平面
        static void SetWorkPlaneForView(gcmp::IUiView* pCurrentView, const gcmp::Vector3d ptBase, const gmep::IMepCurve* pMepCurve);

        /// \brief 判断是否可以继续绘制管道
        static bool CheckAllowDraw(const gmep::IMepCurve* pipe, const gmep::IMepCurve* lastPipe);
        static bool CheckAllowDraw(const gmep::IMepCurve* pipe, const gmep::IMepCurve* lastPipe, const gcmp::Vector3d& secondStartPoint, const gcmp::Vector3d& secondEndPoint);

        ///\brief 判断设备是否有基础
        static bool IsDeviceCanCreatFoundation(const IElement* pElement);
        ///\brief 获取基础所在的关联平面ID以及基础的高度
        static gcmp::ElementId GetFoundationLevelId(gcmp::IDocument* pDoc, double dDeviceHeight, double &dFoundationHeight);
        ///\brief 从属性面板获取部分实例参数
        static bool GetPropertyPanelLevelValue(gcmp::IDocument *pDoc, gcmp::UniIdentity category, int secondKey, double & baseOffset, ElementId &levelElemnetId, double &dLength, double &dWigth, double &dHeight);

        ///\brief 更新管道的标高和设备相同
        static bool UpdateMepCurveLevelIdWithDevice(gcmp::IDocument* pDoc, gmep::IMepCurve* pMepCurve, gmep::IMepDevice* pMepDevice, const gcmp::Vector3d& startPt, const gcmp::Vector3d& endPt, double curveElevation);
        static bool GetHolePropertyValue(gcmp::IDocument *pDoc, gcmp::UniIdentity category, int secondKey, double & baseOffset, ElementId &levelElemnetId, double &dLength, double &dDiameter);
        static bool GetCasingPropertyValue(gcmp::IDocument *pDoc, gcmp::UniIdentity category, int secondKey, double & baseOffset, ElementId &levelElemnetId, double &dLength, double &dDiameter);

        ///\ brief 获取单位转换后的文本字符
        static void GetTextAfterUnitChange(gcmp::IDocument *pDoc, QString &qsText);

        ///\ brief 根据数值获取当前长度单位设置下的字符串
        static bool GetCurrentStringFromConverterStandardString(gcmp::IDocument *pDoc, double dValue, QString &qsText);
        ////\ brief 获取单位转换后的字符串
        static bool GetStringByValue(gcmp::IDocument *pDoc, double dValue, QString &qsText, bool bIsCurrentIndex);

        /// \brief 判断用户输入字符串的值是否符合条件
        /// \brief
        /// \brief 符合条件即在[minValue,maxValuefan]范围内且为整数，需转换为基准单位后比较
        /// \brief 如果不符合条件，使用上次用户输入的符合条件的值；如果符合条件，使用用户输入值
        /// \param pDoc 当前文档
        /// \param disPlaySring 用户输入字符串，如果不符合条件，则改为上次符合条件的值
        /// \param validValue 用户上次输入的可用值，若用户输入值符合条件，则改为用户输入值
        /// \param dMinValue 应满足范围的最小值
        /// \param dMaxValue 应满足范围的最大值
        /// \return bool 是否符合条件
        static bool GetStringInRange(const gcmp::IDocument* pDoc, std::wstring& disPlaySring, int& validValue, double dMinValue, double dMaxValue);

        ///\ brief 获取设备的实例参数中的长宽
        static void GetDeviceLengthAndWidthFromInstanceParameter(const gmep::IMepDevice * pDevice, double &dLength, double &dWidth, bool &bLengthOk, bool &bWidthOK);

        //递归设置链接工作单元这些图形节点的id,解决样式id有效，却得不到对应的样式的bug（GHMEP-15308）sdx 2022.8.1
        static void SetGraphicsStyleIdAndMaterialIdByErgodic(std::vector<const gcmp::IGraphicsNode*> arrNodes, const gcmp::ElementId& m_transientGraphicId);
        //递归设置链接工作单元这些图形节点的id,解决样式id有效，却得不到对应的样式的bug（复制上面的方法，剔除富文本）
        static void SetGraphicsStyleIdAndMaterialIdByErgodicExceptRichText(std::vector<const gcmp::IGraphicsNode*> arrNodes, const gcmp::ElementId& m_transientGraphicId);
        //获取实体的属性参数
        static std::map<std::wstring, gcmp::OwnerPtr<gcmp::IParameterValueStorage>> GetElementPropertyValueList(const gcmp::IDocument *pDoc, const gcmp::ElementId& fittingId);
        /********************汉字字串转成拼音首字母***********/
        static char convert(int n);
        static bool In(wchar_t start, wchar_t end, wchar_t code);
        //将汉字字串转换成拼音首字母，首字不是汉字的不进性转换
        static QString GetChineseSpell(const QString& src);
        /********************汉字字串转成拼音首字母***********/


        static double GetTwoDSymbol_ZoomFactorValue(const std::map<std::wstring, gcmp::OwnerPtr<gcmp::IParameterValueStorage>>& instancePropertyList);

        /// \brief 获取设备图形的二维线
        ///
        /// \param pDocument        
        /// \param pModelView              
        /// \param deviceId                设备Id
        /// \param deviceGraphicLines     二维直线
        /// \return 获取成功返回true，失败返回false
        static bool GetDeviceGrepLines(const gcmp::IDocument* pDocument, const gcmp::IModelView* pModelView, const gcmp::ElementId& deviceId,
            std::vector<gcmp::OwnerPtr<gcmp::ICurve2d>>& deviceGraphicLines);

        /// \brief 镜像T型三通
        ///
        /// \param pMepFitting
        /// \return 是否成功
        static bool MirrorTeeThree(gmep::IMepFitting* pMepFitting);

        /// \brief 镜像四通
        ///
        /// \param pMepFitting
        /// \return 是否成功
        static bool MirrorCross(gmep::IMepFitting* pMepFitting);

        /// \brief 镜像0和1连接点
        ///
        /// \param pMepFitting
        /// \return 是否成功
        static bool MirrorZeroAndOneConnector(gmep::IMepFitting* pMepFitting);

        /// \brief 组合捕捉时获取的捕捉类型只要其中一种是近程捕捉，就确定为近程捕捉
        static bool IsLocalSnap(const gcmp::ISnap* pSnap);

        /// \brief 定位指定构件，并在视图中高亮
        ///
        /// \param pDoc 当前文档
        /// \param deviceId 需要定位构件id
        /// \return 是否成功
        static bool LocateAndHighlightDeviceInModelView(gcmp::IDocument* pDoc, const gcmp::ElementId& deviceId);
    };

}
